package com.abe.libquick.main.video.record;

import android.animation.Animator;
import android.animation.ObjectAnimator;
import android.animation.PropertyValuesHolder;
import android.content.Context;
import android.content.pm.ActivityInfo;
import android.graphics.PixelFormat;
import android.hardware.Camera;
import android.media.AudioManager;
import android.media.MediaRecorder;
import android.os.Environment;
import android.text.TextUtils;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.View;
import android.view.Window;
import android.view.WindowManager;
import android.widget.RelativeLayout;

import com.abe.libcore.base.permission.PermissionUtils;
import com.abe.libcore.base.screen.OnHandlerListener;
import com.abe.libcore.utils.CommonUtils;
import com.abe.libcore.utils.ThreadPoolUtils;
import com.abe.libquick.R;
import com.abe.libquick.R2;
import com.abe.libquick.base.BaseActivity;
import com.abe.libquick.main.video.player.VideoRecordHelper;
import com.abe.libquick.utils.ConstantMBLib;
import com.abe.libquick.utils.NormalUtils;
import com.abe.libquick.utils.quick.EmptyUtils;
import com.abe.libquick.widget.LongTouchBtn;
import com.google.gson.Gson;
import com.mikhaellopez.circularprogressbar.CircularProgressBar;
import com.yanzhenjie.permission.runtime.Permission;

import java.io.File;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;

import butterknife.BindView;

/**
 * @see 1.摄像头翻转的角度 mCamera.setDisplayOrientation(90); 这句必须要的()。
 * @see 2.设置视频文件生成的翻转角度
 * 竖屏情况下：
 * 如果是前置摄像头： mediaRecorder.setOrientationHint(270);
 * 如果是后置摄像头： mediaRecorder.setOrientationHint(90);
 * 横屏情况下：
 * 如果是前置摄像头： mediaRecorder.setOrientationHint(180);
 * 如果是后置摄像头：mediaRecorder.setOrientationHint(0);
 */
public abstract class VideoBaseActivity extends BaseActivity implements SurfaceHolder.Callback, Animator.AnimatorListener,
        MediaRecorder.OnErrorListener, OnHandlerListener {
    public static final int REFRESH_PROGRESS = 0x001;
    public static final int STOP_RECORD = 0x002;
    public static final int RESET_RECORD = 0x003;
    @BindView(R2.id.item_surface_view)
    public SurfaceView mSurfaceView;
    @BindView(R2.id.control)
    public RelativeLayout control;
    @BindView(R2.id.item_start_stop)
    public LongTouchBtn btnStartStop;
    @BindView(R2.id.item_start_stop_progress_bar)
    public CircularProgressBar progressBar;
    public SurfaceHolder mSurfaceHolder;
    public boolean isLongTouch = false;//是否处于长按中
    public boolean isRecording = false;// 标记是否已经在录制
    public MediaRecorder mRecorder;// 音视频录制类
    public Camera mCamera = null;// 相机
    public String currentVideo = "";
    public ObjectAnimator animator_big, animator_normal;
    public int maxVideoLength;// 录制视频最大长度
    public int count = 0;
    private Camera.Size mSize;

    @Override
    public void setContentView(int layoutResID) {
        requestWindowFeature(Window.FEATURE_NO_TITLE);// 去掉标题栏
        getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
                WindowManager.LayoutParams.FLAG_FULLSCREEN);// 设置全屏
        // 设置竖屏显示
        setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
        // 选择支持半透明模式,在有surfaceView的activity中使用。
        getWindow().setFormat(PixelFormat.TRANSLUCENT);
        super.setContentView(layoutResID);
    }

    @Override
    protected void initContent() {
        maxVideoLength = 100;
        if (EmptyUtils.isNotEmpty(bundle()) && bundle().containsKey(VideoRecordHelper.VIDEO_MAX_DURATION)) {
            int max = bundle().getInt(VideoRecordHelper.VIDEO_MAX_DURATION, 10000);
            maxVideoLength = max / 100;
        }
        /*
         * @see progressBar.setProgressWithAnimation(65, animationDuration);
         * @see Default duration = 1500ms(默认1.5秒动画)
         * */
        progressBar.setProgressBarColor(getResources().getColor(R.color.colorTheme));
        progressBar.setBackgroundColor(getResources().getColor(R.color.white));
        progressBar.setProgressBarWidth(10);
        progressBar.setBackgroundProgressBarWidth(5);
        /* 按钮放大动画 */
        PropertyValuesHolder valuesHolder_scaleX_big = PropertyValuesHolder
                .ofFloat("scaleX", 1f, ((float) 4 / (float) 3));
        PropertyValuesHolder valuesHolder_scaleY_big = PropertyValuesHolder
                .ofFloat("scaleY", 1f, ((float) 4 / (float) 3));
        animator_big = ObjectAnimator.ofPropertyValuesHolder(btnStartStop,
                valuesHolder_scaleX_big, valuesHolder_scaleY_big).setDuration(200);
        animator_big.addListener(this);
        /* 按钮缩小动画 */
        PropertyValuesHolder valuesHolder_scaleX_normal = PropertyValuesHolder
                .ofFloat("scaleX", ((float) 4 / (float) 3), 1f);
        PropertyValuesHolder valuesHolder_scaleY_normal = PropertyValuesHolder
                .ofFloat("scaleY", ((float) 4 / (float) 3), 1f);
        animator_normal = ObjectAnimator.ofPropertyValuesHolder(btnStartStop,
                valuesHolder_scaleX_normal, valuesHolder_scaleY_normal).setDuration(100);
        animator_normal.addListener(this);
        btnStartStop.setOnLongTouchListener(new LongTouchBtn.LongTouchListener() {
            @Override
            public void onLongTouch() {
                isLongTouch = true;
                /* 监测到长按事件 */
                if (!isRecording) {
                    /* 开启按钮缩放动画 */
                    animator_big.start();
                    count = 0;
                    localEmptyMsg(REFRESH_PROGRESS);
                }
            }

            @Override
            public void onEndTouch() {
                isLongTouch = false;
                /* 长安结束导致停止录制视频 */
                if (isRecording) {
                    /* 长按结束 */
                    stopRecord();
                } else {
                    count = 0;
                    localEmptyMsg(REFRESH_PROGRESS);
                    animator_normal.start();
                }
            }

            @Override
            public void onStartTouch() {

            }
        }, 500);
        /* 视频缓存路径置空 */
        currentVideo = "";
    }

    /**
     * 初始化相机
     */
    public void initCamera() {
        // 加载相机前释放资源
        if (mCamera != null) {
            releaseCamera();
        }
        // 加载相机
        try {
            if (Camera.getNumberOfCameras() == 2) {
                int mCameraFacing = Camera.CameraInfo.CAMERA_FACING_BACK;// 默认后置摄像头
                mCamera = Camera.open(mCameraFacing);
            } else {
                mCamera = Camera.open();
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        // 相机参数
        Camera.Parameters parameters = mCamera.getParameters();
        // 获取手机支持预览尺寸
        List<Camera.Size> vSizeList = parameters.getSupportedPreviewSizes();
        CommonUtils.INSTANCE.log(new Gson().toJson(vSizeList));
        mSize = getCustomSize(vSizeList);//相机的尺寸
        // 设置竖屏
        parameters.set("orientation", "portrait");
        // 设置预览尺寸
        parameters.setPreviewSize(mSize.width, mSize.height);
        // 获取本机支持对焦模式
        List<String> focusModesList = parameters.getSupportedFocusModes();
        // 增加对聚焦模式的判断
        if (focusModesList.contains(Camera.Parameters.FOCUS_MODE_CONTINUOUS_VIDEO)) {
            // 连续对焦
            parameters.setFocusMode(Camera.Parameters.FOCUS_MODE_CONTINUOUS_VIDEO);
        } else if (focusModesList.contains(Camera.Parameters.FOCUS_MODE_AUTO)) {
            /* 自动对焦 */
            parameters.setFocusMode(Camera.Parameters.FOCUS_MODE_AUTO);
        }
        mCamera.setParameters(parameters);
        /* 设置旋转角度(90-竖屏) */
        mCamera.setDisplayOrientation(90);
    }

    @Override
    protected void onResume() {
        super.onResume();
        initSurface();
        animator_normal.start();
    }

    public void initSurface() {
        PermissionUtils.INSTANCE.request(this, () -> {
            /* 重新初始化录制 */
            mSurfaceHolder = mSurfaceView.getHolder();
            /* 取得holder */
            mSurfaceHolder.setFormat(PixelFormat.TRANSPARENT);
            mSurfaceHolder.setKeepScreenOn(true);
            mSurfaceHolder.addCallback(VideoBaseActivity.this);
            /* holder加入回调接口 */
            mSurfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
        }, Permission.Group.CAMERA);
    }

    @Override
    public void onPause() {
        super.onPause();
        releaseCamera();
    }

    /**
     * 录制初始化
     */
    public void startRecord() {
        AudioManager audioManager = (AudioManager) getSystemService(Context.AUDIO_SERVICE);
        audioManager.setStreamMute(AudioManager.STREAM_SYSTEM, true);
        audioManager.setStreamMute(AudioManager.STREAM_MUSIC, true);
        audioManager.setStreamVolume(AudioManager.STREAM_ALARM, 0, 0);
        audioManager.setStreamVolume(AudioManager.STREAM_DTMF, 0, 0);
        audioManager.setStreamVolume(AudioManager.STREAM_NOTIFICATION, 0, 0);
        audioManager.setStreamVolume(AudioManager.STREAM_RING, 0, 0);
        if (mRecorder == null) {
            mRecorder = new MediaRecorder(); // 创建MediaRecorder
        }
        mRecorder.reset();
        if (mCamera != null) {
            mRecorder.setCamera(mCamera);
        }
        try {
            /* 设置竖屏 */
            mRecorder.setOrientationHint(90);
            // 设置音频采集方式
            mRecorder.setAudioSource(MediaRecorder.AudioSource.CAMCORDER);
            // 设置视频的采集方式
            mRecorder.setVideoSource(MediaRecorder.VideoSource.CAMERA);
            /*
             * @see 设置文件的输出格式 aac_adif, aac_adts, output_format_rtp_avp,
             *      output_format_mpeg2ts,webm
             *
             * @see 注意：这里如果调用了setProfile这个方法的话， 再调用setOutputFormat（）；则会报错。
             * */
            mRecorder.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP);
            // 设置audio的编码格式
            mRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AAC);
            // 设置video的编码格式
            mRecorder.setVideoEncoder(MediaRecorder.VideoEncoder.H264);
            // 设置录制的视频编码比特率
            mRecorder.setVideoEncodingBitRate(5 * 1024 * 1024);// 设置帧频率，然后就清晰了
            // 设置录制的视频帧率,注意文档的说明:
            mRecorder.setVideoFrameRate(30);
            // 设置要捕获的视频的宽度和高度
            //if (EmptyUtils.isNotEmpty(mSize)) {
            //    mSurfaceHolder.setFixedSize(mSize.width, mSize.height);
            //    mRecorder.setVideoSize(mSize.width, mSize.height);
            //} else {
            mSurfaceHolder.setFixedSize(1280, 720);
            mRecorder.setVideoSize(1280, 720);
            //}
            // 设置记录会话的最大持续时间（毫秒）
            mRecorder.setMaxDuration(60 * 1000);
            mRecorder.setPreviewDisplay(mSurfaceHolder.getSurface());
            String path = Environment.getExternalStorageDirectory().getPath();
            if (!TextUtils.isEmpty(path)) {
                File dir = new File(ConstantMBLib.CS_FILE + File.separator + "videos");
                if (!dir.exists()) {
                    boolean x = dir.mkdirs();
                    System.out.println("create Dirs：" + (x ? "success" : "failed"));
                }
                path = dir + File.separator + System.currentTimeMillis() + ".mp4";
                currentVideo = path;
                // 设置输出文件的路径
                mRecorder.setOutputFile(path);
                // 录制出错
                mRecorder.setOnErrorListener(this);
                // 准备录制
                mRecorder.prepare();
                // 开始录制
                mRecorder.start();
                isRecording = true;
                /* 开启进度框变化 */
                ThreadPoolUtils.INSTANCE.execute(new updateProgressThread());
            }
        } catch (Exception e) {
            e.printStackTrace();
            animator_normal.start();
        }
    }

    /**
     * 停止录制
     */
    private void stopRecord() {
        try {
            // 停止录制
            mRecorder.stop();
            // 进入Initial状态（需要重新设置初始化信息）
            mRecorder.reset();
        } catch (Exception e) {
            e.printStackTrace();
        }
        isRecording = false;
        releaseMediaRecorder();
        releaseCamera();
        localEmptyMsg(STOP_RECORD);
    }

    /**
     * 释放MediaRecorder
     */
    private void releaseMediaRecorder() {
        if (mRecorder != null) {
            mRecorder.setPreviewDisplay(null);
            mRecorder.release();
            mRecorder = null;
        }
    }

    /**
     * 释放相机资源
     */
    private void releaseCamera() {
        try {
            if (mCamera != null) {
                mSurfaceHolder.removeCallback(this);
                mCamera.stopPreview();
                mCamera.setPreviewCallback(null);
                mCamera.lock();
                mCamera.release();
            }
        } catch (RuntimeException e) {
            e.printStackTrace();
        } finally {
            mCamera = null;
        }
    }

    @Override
    public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {

    }

    @Override
    public void surfaceCreated(SurfaceHolder holder) {
        try {
            initCamera();
            // 设置显示
            mCamera.setPreviewDisplay(holder);
            mCamera.startPreview();
            mCamera.autoFocus((success, camera) -> {
                if (success) {
                    /* 只有加上了这一句，才会自动对焦。 */
                    camera.cancelAutoFocus();
                }
            });
            mCamera.unlock();
        } catch (Exception e) {
            e.printStackTrace();
            releaseCamera();
            finish();
        }
    }

    @Override
    public void surfaceDestroyed(SurfaceHolder holder) {
        releaseCamera();
        releaseMediaRecorder();
    }

    private Camera.Size getCustomSize(List<Camera.Size> vSizeList) {
        /* 排序规则 */
        CameraSizeComparator sizeComparator = new CameraSizeComparator();
        Camera.Size size = null;
        /* 排序(大到小) */
        Collections.sort(vSizeList, sizeComparator);
        /* 根据需求寻找最佳尺寸 */
        for (int num = 0; num < vSizeList.size(); num++) {
            Camera.Size tempSize = vSizeList.get(num);
            /* 获取屏幕高宽比 */
            float ratio = NormalUtils.getDepthWidthRatio(getApplicationContext());
            float tempRatio = (float) (tempSize.height)
                    / (float) (tempSize.width);
            if (Math.abs(ratio - tempRatio) < 0.1) {
                size = tempSize;
                break;
            }
        }
        if (size == null) {
            size = vSizeList.get(0);
        }
        return size;
    }

    @Override
    public void onBackPressed() {
        isRecording = false;
        setResultCancel();
    }

    @Override
    public void onAnimationCancel(Animator animation) {

    }

    @Override
    public void onAnimationEnd(Animator animation) {
        if (animation.equals(animator_big)) {/* 放大动画 */
            if (isLongTouch) {
                /* 显示进度条 */
                control.setBackgroundResource(R.drawable.item_round_white_shape);
                control.setVisibility(View.VISIBLE);
                progressBar.setVisibility(View.VISIBLE);
                btnStartStop.setVisibility(View.INVISIBLE);
                /* 开启录制 */
                startRecord();
            }
        } else if (animation.equals(animator_normal)) {/* 缩小动画 */
            /* 重置初始化 */
            localEmptyMsg(RESET_RECORD);
        }
    }

    @Override
    public void onAnimationRepeat(Animator animation) {

    }

    @Override
    public void onAnimationStart(Animator animation) {

    }

    @Override
    public void onError(MediaRecorder mr, int what, int extra) {
        releaseMediaRecorder();
        releaseCamera();
        isRecording = false;
    }

    private class CameraSizeComparator implements Comparator<Camera.Size> {
        public int compare(Camera.Size lhs, Camera.Size rhs) {
            return Integer.compare(rhs.width, lhs.width);
        }
    }

    /**
     * 更新进度条
     */
    private class updateProgressThread implements Runnable {

        @Override
        public void run() {
            count = 0;
            while (isRecording && count < maxVideoLength) {
                try {
                    Thread.sleep(100);
                    count++;
                    localEmptyMsg(REFRESH_PROGRESS);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            /* 录制达到最大时长 */
            if (count == maxVideoLength) {
                /* 长按未结束 */
                if (isRecording) {
                    stopRecord();
                    localEmptyMsg(REFRESH_PROGRESS);
                }
            }
        }
    }
}